#pragma once

#include "../core/plato_variable.hh"

namespace plato {

class TestStruct : public StructVariable {
  TestStruct() = delete;
  TestStruct(const TestStruct &) = delete;
  TestStruct(TestStruct &&) = delete;

public:
  IntPtr a;
  FloatPtr b;
  StringPtr c;
  ArrayPtr<Int> d;
  SetPtr<int> e;
  MapPtr<int, Int> f;
  BoolPtr g;

  TestStruct(Domain *domain, VarID parent, PlatoVariableSyncType sync_type)
      : StructVariable(domain, parent, sync_type),
        a(domain->New<Int>(sync_type)), b(domain->New<Float>(sync_type)),
        c(domain->New<String>(sync_type)),
        d(domain->New<Array<Int>>(sync_type)),
        e(domain->New<Set<int>>(sync_type)),
        f(domain->New<Map<int, Int>>(sync_type)),
        g(domain->New<Bool>(sync_type)) {}
  virtual ~TestStruct() {}
  auto static New(Domain *domain, VarID parent, PlatoVariableSyncType sync_type)
      -> std::shared_ptr<TestStruct> {
    return plato::make_shared<TestStruct>(domain->mem_block(), domain, parent,
                                          sync_type);
  }
  virtual auto serialize(PlatoStream &stream) -> bool override {
    stream << id();
    a->serialize(stream);
    b->serialize(stream);
    c->serialize(stream);
    d->serialize(stream);
    e->serialize(stream);
    f->serialize(stream);
    g->serialize(stream);
    return true;
  }
  virtual auto deserialize(PlatoStream &stream) -> bool override {
    stream.skip(sizeof(VarID));
    a->deserialize(stream);
    b->deserialize(stream);
    c->deserialize(stream);
    d->deserialize(stream);
    e->deserialize(stream);
    f->deserialize(stream);
    g->deserialize(stream);
    return true;
  }
  virtual auto copy(Variable *other) -> void override {
    auto *ptr = dynamic_cast<TestStruct *>(other);
    if (!ptr) {
      return;
    }
    a->copy(ptr->a.get());
    b->copy(ptr->b.get());
    c->copy(ptr->c.get());
    d->copy(ptr->d.get());
    e->copy(ptr->e.get());
    f->copy(ptr->f.get());
    g->copy(ptr->g.get());
  }
  virtual auto object_size() -> std::size_t override {
    return sizeof(TestStruct);
  }
  virtual auto copy_default() -> void override {
    a->copy_default();
    b->copy_default();
    c->copy_default();
    d->copy_default();
    e->copy_default();
    f->copy_default();
    g->copy_default();
  }
  virtual auto complete_prototype() -> void override { copy_default(); }
};

} // namespace plato
